package componentes;
import impresion.Impresora;
import impresion.PanelJuego;

import java.awt.Color;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Vector;

public class Tablero {
	
	HashMap<Coordenada,Celda> mapCeldas = new HashMap<Coordenada,Celda>();
	int cantTesorosNorte;
	int cantTesorosSur;
	int size;
	MonitorDeCelda monitor;
	public Impresora impresora;
	PanelJuego panelJ;
	boolean printColor = true;
	boolean printTXT = false;
	
	//Impresora impresora = new Impresora();
	String ganador = "PARTIDA EN CURSO      ";
	boolean finDePartida = false;

	
	public Tablero(int size, int cantTesoros){
		this.monitor = new MonitorDeCelda();
		//size impar > 3
		crearCeldas(size);
		this.size = size;
		this.cantTesorosNorte = cantTesoros;
		this.cantTesorosSur = cantTesoros;
		this.panelJ = new PanelJuego(this.size);
		this.impresora = new Impresora(this.panelJ);
		this.impresora.start();
		asociarCeldas();
		ponerTesorosRandom();
	}
	
	public MonitorDeCelda getMonitor() {
		return this.monitor;
	}
	
	public void restarTesoroNorte(){
		this.cantTesorosNorte -= 1;
		chequearGanador();
	}
	
	public void restarTesoroSur(){
		this.cantTesorosSur -= 1;
		chequearGanador();
	}
	
	//CREAR EL TABLERO
	private void crearCeldas(int n){
		for(int y = 0; y<n;y++){
			for(int x = 0; x<n;x++){
				Coordenada coord = new Coordenada(x,y);
				mapCeldas.put(coord,new Celda(this));
			}
		}
	}
	
	public void asociarCeldas(){
		Collection<Celda> celdas =  mapCeldas.values();
		for(Celda c : celdas)
			c.setLindantes();
	}
	
	public Celda celdaDeCoordIgualA(Coordenada coord){
		return mapCeldas.get(retornarCoord(coord));
	}
	
	public Celda lindanteNorte(Celda celda){
		Coordenada coordCelda = dameCoordDe(celda);
		return celdaDeCoordIgualA(new Coordenada(coordCelda.getX(),coordCelda.getY()+1));

	}
	
	public Celda lindanteSur(Celda celda){
		Coordenada coordCelda = dameCoordDe(celda);
		return celdaDeCoordIgualA(new Coordenada(coordCelda.getX(),coordCelda.getY()-1));

	}
	
	public Celda lindanteEste(Celda celda){
		Coordenada coordCelda = dameCoordDe(celda);
		return celdaDeCoordIgualA(new Coordenada(coordCelda.getX()+1,coordCelda.getY()));

	}
	
	public Celda lindanteOeste(Celda celda){
		Coordenada coordCelda = dameCoordDe(celda);
		return celdaDeCoordIgualA(new Coordenada(coordCelda.getX()-1,coordCelda.getY()));

	}
	
	
	
	//Crear y UBICAR TESOROS
	//No puede ubicarse en los bordes ni en el medio
	//coordenada ocupada o con tesoro rompe!
	
	public void ponerTesorosRandom(){
		List<Coordenada> csTesoroSur = posiblesCoordenadasTesoroSur();
		List<Coordenada> csTesoroNorte = posiblesCoordenadasTesoroNorte();
		for(int i=this.cantTesorosNorte;i>0;i--){
			Coordenada coordS = popRandom(csTesoroSur);
			Coordenada coordN = popRandom(csTesoroNorte);
			ponerTesoro(coordS.getX(),coordS.getY());
			ponerTesoro(coordN.getX(),coordN.getY());
		}
	}
	
	public <T> T popRandom(List<T> list){
		int randomIndex = (int) (Math.random()*list.size());
		T randomElem = list.get(randomIndex);
		list.remove(randomElem);
		return randomElem;
	}
	
	public List<Coordenada> posiblesCoordenadasTesoroSur(){
		List<Coordenada> coordsSur = new Vector<Coordenada>();
		for(int columna = 1; columna<size-1;columna++){
			for(int fila = 1; fila<(size-1)/2;fila++){
				coordsSur.add(new Coordenada(columna,fila));
			}
		}
		return coordsSur;
	}
	
	public List<Coordenada> posiblesCoordenadasTesoroNorte(){
		List<Coordenada> coordsNorte = new Vector<Coordenada>();
		for(int columna = 1; columna<size-1;columna++){
			for(int fila = ((size-1)/2)+1; fila<size-1;fila++){
				coordsNorte.add(new Coordenada(columna,fila));
			}
		}
		return coordsNorte;
	}
	public void ponerTesoro(int x,int y){
		mapCeldas.get(retornarCoord(x,y)).ponerTesoro();
	}
	
	//UBICAR JUGADORES
	//coordenada ocupada o con tesoro rompe!
	//pensar movimientos del jugador
	//pensar quien conoce a quien...
	
	
	public void ponerJugadorSur(int x,int y,List<Movimiento> estrategia){
		new JugadorSur(mapCeldas.get(retornarCoord(x,y)),estrategia);
	}
	
	public void ponerJugadorNorte(int x,int y,List<Movimiento> estrategia){
		new JugadorNorte(mapCeldas.get(retornarCoord(x,y)),estrategia);
	}
	
	

	public int getSize() {
		return size;
	}

	public void setSize(int size) {
		this.size = size;
	}
	
	@SuppressWarnings("deprecation")
	public void accionarJugadores(boolean start){
		List<Jugador> js = new Vector<Jugador>();
		for(Celda celda: mapCeldas.values()){
			if (celda.ocupada()){
				js.add(celda.getJugador());
			}
		}
		for(Jugador j: js){
			if(start)
				j.start();
			else
				j.stop();
		}
	}
	
	public void startJugadores(){
		accionarJugadores(true);
	}
	
	private void stopJugadores() {
		accionarJugadores(false);
	}

	private List<Coordenada> posiblesRespaldos(Coordenada coord){
		List<Coordenada> respaldos = new Vector<Coordenada>();
		
		if(mapCeldas.get(coord).getCeldaOeste()!=null)
			respaldos.add(coord.coordenadaOeste());
		if(mapCeldas.get(coord).getCeldaEste()!=null)
			respaldos.add(coord.coordenadaEste());
		
		return respaldos;
	}
	
	private List<Coordenada> posiblesRespaldosSur(Coordenada coord){
		List<Coordenada> respaldosSur = posiblesRespaldos(coord);

		if(mapCeldas.get(coord).getCeldaSur()!=null)
			respaldosSur.add(coord.coordenadaSur());

		return respaldosSur;
	}
	
	private List<Coordenada> posiblesRespaldosNorte(Coordenada coord){
		List<Coordenada> respaldosNorte = posiblesRespaldos(coord);
		
		if(mapCeldas.get(coord).getCeldaNorte()!=null)
			respaldosNorte.add(coord.coordenadaNorte());

		return respaldosNorte;
	}
	
	public Coordenada dameCoordDe(Celda celda){
		java.util.Iterator<Coordenada> it = mapCeldas.keySet().iterator();
		while(it.hasNext()){
		  Coordenada coord = it.next();
		  if(mapCeldas.get(coord) == celda)
			  return coord;
		}
		return null;
	}
	
	public boolean sinRespaldo(Celda celda) {
		
		List<Coordenada> posiblesRespaldos = posiblesRespaldosNorte(dameCoordDe(celda));
		if(celda.getJugador().necesitoRespaldosAlSur())
			posiblesRespaldos = posiblesRespaldosSur(dameCoordDe(celda));

			for(Coordenada coord : posiblesRespaldos){
				if(mapCeldas.get(retornarCoord(coord)).ocupada(celda.getJugador()))
					return false;
			}

		return true;
	}
	
	public Coordenada retornarCoord(int x,int y){
		Coordenada coord = new Coordenada(x,y);
		for(Coordenada c : mapCeldas.keySet())
			if(c.esIgual(coord))
				return c;
		return null;
	}
	
	public Coordenada retornarCoord(Coordenada coord){
		for(Coordenada c : mapCeldas.keySet())
			if(c.esIgual(coord))
				return c;
		return null;
	}

	public void chequearGanador() {
		if(cantTesorosNorte == 0){
			this.ganador="AH GANADO EQUIPO SUR  ";
			finDePartida=true;
		}else{
			if(cantTesorosSur == 0){
				this.ganador="AH GANADO EQUIPO NORTE";
				finDePartida=true;
			}
		}
	}
	
	public void controlDeImpresion() throws InterruptedException{
		
		if (printColor) imprimirPorImpresora();
		if (printTXT) imprimirTXT();
		
		if (finDePartida) stopJugadores();	
	}
	
	public void imprimirTXT() throws InterruptedException{
		impresora.imprimirTXT(this);
	}
	public void print(){
		for(int c=size-1; c>=0; c--){
			for(int f=0; f<size; f++){
			Celda celdaAImprimir = mapCeldas.get(retornarCoord(f, c));
			System.out.print(celdaAImprimir);
		}
			System.out.println();
		}
		System.out.println("------------------"+ganador+ "--"+"tesorosNorte: "+cantTesorosNorte+
				" tesorosSur: "+cantTesorosSur);
										     
	}
	
	public void imprimir() throws InterruptedException{
		
		List<Color> cs = new Vector<Color>();
		for(int c=size-1; c>=0; c--){
			for(int f=0; f<size; f++){
			Celda celdaAImprimir = mapCeldas.get(retornarCoord(f, c));
			cs.add(celdaAImprimir.miColor());
		}
		this.impresora.agregarAColaDeImpresion(cs);
		}
	}

	public void imprimirPorImpresora() throws InterruptedException{
		this.impresora.imprimirGUI(this);
	}
	
	public void cambiarSleepTimeDeImpresion(int n){
		impresora.cambiarSleepTimeDeImpresion(n);
	}
	
	public void imprimirColor(boolean c) {
		printColor=c;
	}

	public void imprimirTXT(boolean c) {
		printTXT=c;
	}

		
}
